#include "form_setting_network.h"
#include "ui_form_setting_network.h"

// add nacessary includes here
#include "utils/configure/configure_bll.h"
#include "utils/firmware/firmware_bll.h"
#include "ui/share/form_prompt_dlg.h"

#define DEF_IP_DOT_SPLIT_SIZE           4
#define DEF_MAC_DOT_SPLIT_SIZE          6

/*
 * Function:    FormSettingNetwork
 * Description: The default constructor
 * Paramer:     void
 * Return:
 */
FormSettingNetwork::FormSettingNetwork(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::FormSettingNetwork)
{
    qDebug() << Q_FUNC_INFO;

    ui->setupUi(this);
}

/*
 * FormHistoryResult:    ~FormSettingNetwork
 * Description: The default destructor
 * Paramer:     void
 * Return:
 */
FormSettingNetwork::~FormSettingNetwork()
{
    qDebug() << Q_FUNC_INFO;

    delete ui;
}

/*
 * Function:    getInstance
 * Description: Get an instance of "FormSettingNetwork" class, if exist, return it
 * Paramer:     QWidget *pParent - the pointer of QWidget class
 * Return:      the pointer of "FormSettingNetwork" class
 */
FormSettingNetwork* FormSettingNetwork::getInstance(QWidget *pParent)
{
    static FormSettingNetwork *pNew = NULL;
    if(!pNew) {
        qDebug() << Q_FUNC_INFO;

        // Create a new object if it doesn't exist
        pNew = new FormSettingNetwork(pParent);
        if(NULL == pNew) return NULL;

        // After constructing object, initialize the object
        pNew->_initialze();

        // Initialize control's UI
        pNew->_initUi();

        // Hide widget firstly
        pNew->hide();
    }
    else {
        // Set the parent object
        pNew->setParent(pParent);
    }

    return pNew;
}

/*
 * Function:    _initialze
 * Description: After constructing object, initialize the object
 * Paramer:     void
 * Return:      void
 */
void FormSettingNetwork::_initialze()
{
    qDebug() << Q_FUNC_INFO;

    // Signal-slot initialization
    std::vector<bool> vecConnect;
    vecConnect.push_back(QObject::connect(this, SIGNAL(signalRefreshUI()), this, SLOT(slotRefreshUI()), static_cast<Qt::ConnectionType>(Qt::AutoConnection | Qt::UniqueConnection)));
    for(int i=0; i<(int)vecConnect.size(); i++) {
        Q_ASSERT(vecConnect.at(i));
    }

    // Load the network params
    ST_CFG_NETWORK stNetwork;
    int nRetVal = ConfigureBLL::getInstance(this)->loadCfgNetwork(stNetwork);
    if(0 == nRetVal) {
        if(!stNetwork.stNetLocal.sIpAddr.isEmpty() && !stNetwork.stNetLocal.sMask.isEmpty() && !stNetwork.stNetLocal.sGetway.isEmpty()) {
            // Config local static IP info
            FirmwareBLL::getInstance(this)->configStaticNet(stNetwork.stNetLocal.sIpAddr, stNetwork.stNetLocal.sMask, stNetwork.stNetLocal.sGetway, stNetwork.stNetLocal.sNetwork);
        }
    }
}

/*
* Function:		_initUi
* Description:	Init the window style
* Paramer:		void
* Return:		void
*/
void FormSettingNetwork::_initUi()
{
    qDebug() << Q_FUNC_INFO;

    // Displays the background image of the window
    QWidget::setAttribute(Qt::WA_StyledBackground);

    SET_STYLE_SHEET(QString(":/%1/setting/%2.qss").arg("skin_1").arg(this->objectName()));

    ui->lineEdit_MacAddr->setDisabled(true);
    ui->checkBox_Auto->setVisible(false);

    QValidator *vldDigit = new QRegExpValidator(QRegExp("(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)"));
    QValidator *vldDigit2 = new QRegExpValidator(QRegExp("^[0-9]{5}$"));

    ui->lineEdit_IpAddr_1->setValidator(vldDigit);
    ui->lineEdit_IpAddr_2->setValidator(vldDigit);
    ui->lineEdit_IpAddr_3->setValidator(vldDigit);
    ui->lineEdit_IpAddr_4->setValidator(vldDigit);
    ui->lineEdit_Mask_1->setValidator(vldDigit);
    ui->lineEdit_Mask_2->setValidator(vldDigit);
    ui->lineEdit_Mask_3->setValidator(vldDigit);
    ui->lineEdit_Mask_4->setValidator(vldDigit);
    ui->lineEdit_Gateway_1->setValidator(vldDigit);
    ui->lineEdit_Gateway_2->setValidator(vldDigit);
    ui->lineEdit_Gateway_3->setValidator(vldDigit);
    ui->lineEdit_Gateway_4->setValidator(vldDigit);
    ui->lineEdit_IpAddr_11->setValidator(vldDigit);
    ui->lineEdit_IpAddr_12->setValidator(vldDigit);
    ui->lineEdit_IpAddr_13->setValidator(vldDigit);
    ui->lineEdit_IpAddr_14->setValidator(vldDigit);
    ui->lineEdit_Port->setValidator(vldDigit2);

    ui->lineEdit_IpAddr_1->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_IpAddr_2->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_IpAddr_3->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_IpAddr_4->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_Mask_1->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_Mask_2->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_Mask_3->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_Mask_4->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_Gateway_1->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_Gateway_2->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_Gateway_3->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_Gateway_4->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_IpAddr_11->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_IpAddr_12->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_IpAddr_13->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_IpAddr_14->setInputMethodHints(Qt::ImhDigitsOnly);
    ui->lineEdit_Port->setInputMethodHints(Qt::ImhDigitsOnly);
}

/*
* Function:		slotRefreshUI
* Description:	The slot that refresh UI info
* Paramer:		void
* Return:		void
*/
void FormSettingNetwork::slotRefreshUI()
{
    qDebug() << Q_FUNC_INFO;

    // Load the network params
    ST_CFG_NETWORK stNetwork;
    int nRetVal = ConfigureBLL::getInstance(this)->loadCfgNetwork(stNetwork);
    if(0 == nRetVal) {
        _refreshNetworkUI(stNetwork);
    }

    ui->tabWidget->setCurrentIndex(0);
}

/*
* Function:		on_pushButton_Ping_clicked
* Description:	Ping to specify the IP
* Paramer:		void
* Return:		void
*/
void FormSettingNetwork::on_pushButton_Ping_clicked()
{
    qDebug() << Q_FUNC_INFO;

    QString sIP = QString("%1.%2.%3.%4")
            .arg(ui->lineEdit_IpAddr_11->text().trimmed())
            .arg(ui->lineEdit_IpAddr_12->text().trimmed())
            .arg(ui->lineEdit_IpAddr_13->text().trimmed())
            .arg(ui->lineEdit_IpAddr_14->text().trimmed());

    // Implement ping function
    QString sPingOutput;
    bool bLive = FirmwareBLL::getInstance(this)->pingIp(sPingOutput, sIP, 1000);
    if(bLive) {
        FormPromptWidget::getInstance(this)->setPromptInfo(tr("Prompt"), tr("IP address online"));
    }
    else {
        FormPromptWidget::getInstance(this)->setPromptInfo(tr("Prompt"), tr("IP address offline"));
    }

    qDebug() << Q_FUNC_INFO << bLive;
}

void FormSettingNetwork::on_pushButton_PingEx_clicked()
{
    qDebug() << Q_FUNC_INFO;

    QString sIP = QString("%1.%2.%3.%4")
            .arg(ui->lineEdit_IpAddr_11->text().trimmed())
            .arg(ui->lineEdit_IpAddr_12->text().trimmed())
            .arg(ui->lineEdit_IpAddr_13->text().trimmed())
            .arg(ui->lineEdit_IpAddr_14->text().trimmed());

    int nPort = ui->lineEdit_Port->text().toInt();

    // Determine if the IP address and port are online
    bool bLive = FirmwareBLL::getInstance(this)->pingIpPort(sIP, nPort, 1000);
    if(bLive) {
        FormPromptWidget::getInstance(this)->setPromptInfo(tr("Prompt"), tr("IP address and port online"));
    }
    else {
        FormPromptWidget::getInstance(this)->setPromptInfo(tr("Prompt"), tr("IP address and port offline"));
    }

    qDebug() << Q_FUNC_INFO << bLive;
}

/*
* Function:		changeEvent
* Description:	Triggers an event before it is switch language
* Paramer:		QShowEvent *event - the pointer of "QEvent"
* Return:		void
*/
void FormSettingNetwork::changeEvent(QEvent *e)
{
    switch (e->type()) {
    case QEvent::LanguageChange:
    {
        ui->retranslateUi(this);
        qDebug() << Q_FUNC_INFO;
        break;
    }
    default:
        break;
    }

    QWidget::changeEvent(e);
}

/*
* Function:		hideEvent
* Description:	Triggers an event the hide the window
* Paramer:		QHideEvent *event - the pointer of "QHideEvent"
* Return:		void
*/
void FormSettingNetwork::hideEvent(QHideEvent *event)
{
    Q_UNUSED(event);

    _saveNetworkInfo();
}

/*
* Function:		_refreshNetworkUI
* Description:	Refresh network info
* Paramer:		ST_CFG_NETWORK stNetwork - the network info
* Return:		void
*/
void FormSettingNetwork::_refreshNetworkUI(ST_CFG_NETWORK stNetwork)
{
    qDebug() << Q_FUNC_INFO;

    // Load the local IP info from config file & display
    _refreshLocalInfo(stNetwork);

    // Load the remote IP & port from config file & display
    _refreshServerInfo(stNetwork);
}

/*
* Function:		_refreshLocalInfo
* Description:	Load the local IP info from config file & display
* Paramer:		ST_CFG_NETWORK stNetwork - the network info
* Return:		void
*/
void FormSettingNetwork::_refreshLocalInfo(ST_CFG_NETWORK stNetwork)
{
    qDebug() << Q_FUNC_INFO;

    // Clear the text of static/dynamic ip
    _clearIpText(false);

    QString sIP = stNetwork.stNetLocal.sIpAddr;
    QString sNetMask = stNetwork.stNetLocal.sMask;
    QString sGateWay = stNetwork.stNetLocal.sGetway;

    // Config local static IP info
    FirmwareBLL::getInstance(this)->configStaticNet(stNetwork.stNetLocal.sIpAddr, stNetwork.stNetLocal.sMask, stNetwork.stNetLocal.sGetway, stNetwork.stNetLocal.sNetwork);

    // Local IP address
    QStringList lstSectionA = sIP.split(".");
    if(DEF_IP_DOT_SPLIT_SIZE == lstSectionA.size()) {
        ui->lineEdit_IpAddr_1->setText(lstSectionA.at(0));
        ui->lineEdit_IpAddr_2->setText(lstSectionA.at(1));
        ui->lineEdit_IpAddr_3->setText(lstSectionA.at(2));
        ui->lineEdit_IpAddr_4->setText(lstSectionA.at(3));
    }

    QStringList lstSectionB = sNetMask.split(".");
    if(DEF_IP_DOT_SPLIT_SIZE == lstSectionB.size()) {
        ui->lineEdit_Mask_1->setText(lstSectionB.at(0));
        ui->lineEdit_Mask_2->setText(lstSectionB.at(1));
        ui->lineEdit_Mask_3->setText(lstSectionB.at(2));
        ui->lineEdit_Mask_4->setText(lstSectionB.at(3));
    }

    QStringList lstSectionC = sGateWay.split(".");
    if(DEF_IP_DOT_SPLIT_SIZE == lstSectionC.size()) {
        ui->lineEdit_Gateway_1->setText(lstSectionC.at(0));
        ui->lineEdit_Gateway_2->setText(lstSectionC.at(1));
        ui->lineEdit_Gateway_3->setText(lstSectionC.at(2));
        ui->lineEdit_Gateway_4->setText(lstSectionC.at(3));
    }
    else {
        if(DEF_IP_DOT_SPLIT_SIZE == lstSectionA.size()) {
            ui->lineEdit_Gateway_1->setText(lstSectionA.at(0));
            ui->lineEdit_Gateway_2->setText(lstSectionA.at(1));
            ui->lineEdit_Gateway_3->setText(lstSectionA.at(2));
            ui->lineEdit_Gateway_4->setText("1");
        }
    }

    // Get the MAC address of the host
    QString sMacAddr = FirmwareBLL::getInstance(this)->getHostMacAddress(false);
    ui->lineEdit_MacAddr->setText(sMacAddr);
}

/*
* Function:		_refreshServerInfo
* Description:	Load the remote IP & port from config file & display
* Paramer:		ST_CFG_NETWORK stNetwork - the network info
* Return:		void
*/
void FormSettingNetwork::_refreshServerInfo(ST_CFG_NETWORK stNetwork)
{
    qDebug() << Q_FUNC_INFO;

    // Get the network info
    ConfigureBLL::getInstance(this)->loadCfgNetwork(stNetwork);

    // Server IP address
    QStringList lstSection = stNetwork.stNetServer.sIpAddr.split(".");
    if(DEF_IP_DOT_SPLIT_SIZE == lstSection.size()) {
        ui->lineEdit_IpAddr_11->setText(lstSection.at(0));
        ui->lineEdit_IpAddr_12->setText(lstSection.at(1));
        ui->lineEdit_IpAddr_13->setText(lstSection.at(2));
        ui->lineEdit_IpAddr_14->setText(lstSection.at(3));
    }
    else {
        ui->lineEdit_IpAddr_11->setText("");
        ui->lineEdit_IpAddr_12->setText("");
        ui->lineEdit_IpAddr_13->setText("");
        ui->lineEdit_IpAddr_14->setText("");
    }

    // Server port
    if(0 <= stNetwork.stNetServer.nPort) {
        ui->lineEdit_Port->setText(QString::number(stNetwork.stNetServer.nPort));
    }
    else {
        ui->lineEdit_Port->setText("");
    }

    // Upload data to LIS
    ui->checkBox_Auto->setChecked(stNetwork.bAutoUpload);
}

/*
 * Function:    _saveNetworkInfo
 * Description: Save the network info
 * Paramer:     void
 * Return:      int - the error code, 0:success; otherwise: failure
 */
void FormSettingNetwork::_saveNetworkInfo()
{
    ST_CFG_NETWORK stNetwork;

    // Static IP address
    stNetwork.stNetLocal.sIpAddr = ui->lineEdit_IpAddr_1->text().trimmed() + "."
            + ui->lineEdit_IpAddr_2->text().trimmed() + "."
            + ui->lineEdit_IpAddr_3->text().trimmed() + "."
            + ui->lineEdit_IpAddr_4->text().trimmed();
    stNetwork.stNetLocal.sMask = ui->lineEdit_Mask_1->text().trimmed() + "."
            + ui->lineEdit_Mask_2->text().trimmed() + "."
            + ui->lineEdit_Mask_3->text().trimmed() + "."
            + ui->lineEdit_Mask_4->text().trimmed();
    stNetwork.stNetLocal.sNetwork = ui->lineEdit_Gateway_1->text().trimmed() + "."
            + ui->lineEdit_Gateway_2->text().trimmed() + "."
            + ui->lineEdit_Gateway_3->text().trimmed() + "."
            + "0";
    stNetwork.stNetLocal.sGetway = ui->lineEdit_Gateway_1->text().trimmed() + "."
            + ui->lineEdit_Gateway_2->text().trimmed() + "."
            + ui->lineEdit_Gateway_3->text().trimmed() + "."
            + ui->lineEdit_Gateway_4->text().trimmed();
    stNetwork.stNetLocal.sMacAddr = ui->lineEdit_MacAddr->text().trimmed().toUpper();

#ifdef QT_NO_DEBUG
    // Config static IP info
    FirmwareBLL::getInstance(this)->configStaticNet(stNetwork.stNetLocal.sIpAddr, stNetwork.stNetLocal.sMask, stNetwork.stNetLocal.sGetway, stNetwork.stNetLocal.sNetwork);
#endif

    // Server IP address
    stNetwork.stNetServer.sIpAddr = ui->lineEdit_IpAddr_11->text().trimmed() + "."
            + ui->lineEdit_IpAddr_12->text().trimmed() + "."
            + ui->lineEdit_IpAddr_13->text().trimmed() + "."
            + ui->lineEdit_IpAddr_14->text().trimmed();
    stNetwork.stNetServer.nPort = ui->lineEdit_Port->text().trimmed().toInt();

    ConfigureBLL::getInstance(this)->saveCfgNetwork(stNetwork);
}

/*
 * Function:    _clearIpText
 * Description: Clear the text of static/dynamic ip
 * Paramer:     void
 * Return:      void
 */
void FormSettingNetwork::_clearIpText(bool bDynamicIP)
{
    qDebug() << Q_FUNC_INFO;

    ui->lineEdit_IpAddr_1->setText("");
    ui->lineEdit_IpAddr_2->setText("");
    ui->lineEdit_IpAddr_3->setText("");
    ui->lineEdit_IpAddr_4->setText("");
    ui->lineEdit_Mask_1->setText("");
    ui->lineEdit_Mask_2->setText("");
    ui->lineEdit_Mask_3->setText("");
    ui->lineEdit_Mask_4->setText("");
    ui->lineEdit_Gateway_1->setText("");
    ui->lineEdit_Gateway_2->setText("");
    ui->lineEdit_Gateway_3->setText("");
    ui->lineEdit_Gateway_4->setText("");

    ui->lineEdit_IpAddr_1->setDisabled(bDynamicIP);
    ui->lineEdit_IpAddr_2->setDisabled(bDynamicIP);
    ui->lineEdit_IpAddr_3->setDisabled(bDynamicIP);
    ui->lineEdit_IpAddr_4->setDisabled(bDynamicIP);
    ui->lineEdit_Mask_1->setDisabled(bDynamicIP);
    ui->lineEdit_Mask_2->setDisabled(bDynamicIP);
    ui->lineEdit_Mask_3->setDisabled(bDynamicIP);
    ui->lineEdit_Mask_4->setDisabled(bDynamicIP);
    ui->lineEdit_Gateway_1->setDisabled(bDynamicIP);
    ui->lineEdit_Gateway_2->setDisabled(bDynamicIP);
    ui->lineEdit_Gateway_3->setDisabled(bDynamicIP);
    ui->lineEdit_Gateway_4->setDisabled(bDynamicIP);
}
